package httpclient

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"github.com/gogf/gf/errors/gerror"
	"github.com/gogf/gf/os/glog"
	"gitlab.local/DO-module/new-filemanage-module/src/core"
	"gitlab.local/DO-module/new-filemanage-module/src/core/network"
	"gitlab.local/DO-module/new-filemanage-module/src/core/nginx"
	"mime/multipart"
	"net/http"
	"net/url"
	"time"
)

type Poster interface {
	PostForm(url string, values url.Values, header http.Header) (*http.Response, error)
}

type Getter interface {
	Get(url string, header http.Header) (*http.Response, error)
}

type PostGet interface {
	Poster
	Getter
}

type HttpClient struct {
	macGetter      core.MacGetter
	lanIpGetter    network.LanIpGetter
	httpPortGetter nginx.PortGetter
}

func New(wanIpGetter network.LanIpGetter,
	httpPortGetter nginx.PortGetter) *HttpClient {
	return &HttpClient{
		lanIpGetter:    wanIpGetter,
		httpPortGetter: httpPortGetter,
	}
}

func (Self *HttpClient) setAuthHeader(header *http.Header) {

	mac, err := Self.macGetter.GetMacLastNChars("eth0", 12)
	if err != nil {
		glog.Error(err)
	}

	ip, err := Self.lanIpGetter.GetLanIp()
	if err != nil {
		glog.Error(err)
	}

	port, err := Self.httpPortGetter.GetHttpPort()
	if err != nil {
		glog.Error(err)
	}

	header.Set("Authorization", mac)
	header.Set("Lanip", fmt.Sprintf("%s:%d", ip, port))
}

func (Self *HttpClient) createMultiPart(values url.Values) (string, *bytes.Buffer, error) {

	var b bytes.Buffer
	w := multipart.NewWriter(&b)
	defer w.Close()
	for k, v := range values {
		field, err := w.CreateFormField(k)
		if err != nil {
			return "", nil, gerror.Wrap(err, "failed to create form field")
		}
		_, err = field.Write([]byte(v[0]))
		if err != nil {
			return "", nil, gerror.Wrap(err, "failed to write field")
		}
	}
	return w.FormDataContentType(), &b, nil
}

func (Self *HttpClient) Get(url string, header http.Header) (*http.Response, error) {
	tr := http.DefaultTransport.(*http.Transport).Clone()
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

	c := http.Client{Transport: tr}
	c.Timeout = time.Second * 10

	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, gerror.Wrap(err, "failed to new request")
	}
	if header != nil {
		req.Header = header
	}
	req.Close = true //关闭重用请求
	req.Header.Set("Referer", url)
	req.Header.Set("User-Agent", "TOS/6.0")
	Self.setAuthHeader(&req.Header)

	return c.Do(req)
}

func (Self *HttpClient) PostForm(url string, values url.Values, header http.Header) (*http.Response, error) {

	tr := http.DefaultTransport.(*http.Transport).Clone()
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

	c := http.Client{Transport: tr}
	c.Timeout = time.Second * 10
	defer c.CloseIdleConnections()

	contentType, mwBuf, err := Self.createMultiPart(values)
	if err != nil {
		return nil, gerror.Wrap(err, "failed to")
	}

	req, err := http.NewRequest(http.MethodPost, url, mwBuf)
	if err != nil {
		return nil, gerror.Wrap(err, "failed to new request")
	}
	if header != nil {
		req.Header = header
	}
	req.Close = true //关闭重用请求
	req.Header.Set("Content-Type", contentType)
	req.Header.Set("Referer", url)
	req.Header.Set("User-Agent", "TOS/5.1")
	req.Header.Set("Cache-Control", "no-cache")
	req.Header.Set("Pragma", "no-cache")
	Self.setAuthHeader(&req.Header)

	return c.Do(req)
}
